/*
 *  $TEAM_NAME Space Trader
 */
package views;

import models.Galaxy;
import models.Player;
import models.StarSystem;


import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
import javax.swing.JLabel;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Dimension;
import java.awt.RenderingHints;
import java.awt.Color;
import java.awt.AlphaComposite;
import java.awt.geom.Point2D;
import java.awt.Component;
import java.awt.Point;

/**
 * A panel that contains the view of the galaxy map
 * @author bradley
 * @version 1.0
 */
public class MapPanel extends JPanel {
	
	/**
	 * Field POINTTWOFIVE.
	 * (value is 0.25)
	 */
	private static final float POINTTWOFIVE = .25f;
	
	/**
	 * Field TWO.
	 * (value is 2)
	 */
	private static final int TWO = 2;
	
	/**
	 * Field HUNDRED.
	 * (value is 100)
	 */
	private static final int HUNDRED = 100;
	
	/**
	 * field
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * field
	 */
	private final Galaxy galaxy;
    
	/**
	 * field
	 */
	private final Player player;

	/**
	 * field
	 */
	private MapOverlayPanel overlay;
    
	/**
	 * field
	 */
	private final JLabel fuelLabel;

	/**
	 * field
	 */
	private BufferedImage backgroundImage = null;

    /**
     * Default constructor
     * @param galaxy
     * @param player
     */
    public MapPanel(Player player, Galaxy galaxy) {
        //Get the planets names
        try {
            backgroundImage = ImageIO.read(new File("resources/MapBackground.png"));
        } catch (IOException e) {
            System.err.println(e);		//Should we throw an exception here instead?
            System.exit(1);
        }
        
        //Set the local variables
        this.galaxy = galaxy;
        this.player = player;

        fuelLabel = new JLabel();
        super.add(fuelLabel);

        //Set the layout properties
        super.setLayout(null);
    }

    // This is horrible
    /**
     * Method update.
     */
    public void update() {
        removeAll();

        final StarSystem current = player.getLocation();

        for (StarSystem ss : galaxy.getStarSystems()) {
            StarSystemPanel ssv = new StarSystemPanel(ss);
            
            if (ss.equals(current)) {
                ssv.setCurrent(true);
            } else if (ss.distanceTo(current) <= player.getShip().getRange()) {
                ssv.setInRange(true);
            } else {
            	ssv.setInRange(false);
            }

            add(ssv);
        }

        fuelLabel.setText("Fuel Remiaining: " 
        +  player.getShip().getFuelTank().getCurrentFuel());

        layoutSubviews();
    }

    /**
     * Method paintComponent.
     * @param g Graphics
     */
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        final Graphics2D gfx = (Graphics2D) g;

        gfx.setRenderingHint(
        		RenderingHints.KEY_ANTIALIASING, 
        		RenderingHints.VALUE_ANTIALIAS_ON);

        final Dimension size = getSize();

        // Background
        if(gfx.drawImage(backgroundImage, 0, 0, size.width, 
        		size.height, Color.BLACK, null)){
        	System.out.print("");
        }

        // In Range Oval
        gfx.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 
        		POINTTWOFIVE));

        final StarSystem ss = player.getLocation();
        final Point2D location = ss.getLocation();

        final int x = (int) (location.getX() * size.width);
        final int y = (int) (location.getY() * size.height);
        final double radius = player.getShip().getRange();

        final int rx = (int) (radius * size.width);
        final int ry = (int) (radius * size.height);

        gfx.setColor(Color.GRAY);
        gfx.fillOval(x - rx, y - ry, TWO * rx, TWO * ry);

        gfx.setColor(Color.BLUE);
        gfx.drawOval(x - rx, y - ry, TWO * rx, TWO * ry);

        gfx.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f));
    }

    /**
     * Method addOverlay.
     * @param overlay MapOverlayPanel
     */
    public void addOverlay(MapOverlayPanel overlay) {
        if (this.overlay != null) {
            removeOverlay();
        }

        add(overlay, 0);
        this.overlay = overlay;
        layoutSubviews();
    }

    /**
     * Method removeOverlay.
     */
    public void removeOverlay() {
        if (overlay != null) {
            remove(overlay);
        }

        repaint();
    }

    /**
     * Method setBounds.
     * @param x int
     * @param y int
     * @param width int
     * @param height int
     */
    public void setBounds(int x, int y, int width, int height) {
        super.setBounds(x, y, width, height);
        layoutSubviews();
    }

    /**
     * Method layoutSubviews.
     */
    private void layoutSubviews() {
        final Dimension size = getSize();

        for (Component component : getComponents()) { 
            if (component instanceof StarSystemPanel) {
                StarSystemPanel ssv = (StarSystemPanel) component;
                StarSystem ss = ssv.getStarSystem();

                Point2D location = ss.getLocation();

                int x = (int) (location.getX() * size.width);
                int y = (int) (location.getY() * size.height);

                double radius = ss.getRadius();
                int rx = (int) (radius * size.width);
                int ry = (int) (radius * size.height);

                ssv.setLocation(new Point(x - (rx >> 1), y - (ry >> 1)));

                ssv.setSize(TWO * rx, TWO * ry);
            }
        }

        if (overlay != null) {
            final StarSystem overViewSystem = overlay.getStarSystem();
            final Point2D location = overViewSystem.getLocation();

            final int width = HUNDRED;
            final int height = HUNDRED;

            final double radius = overlay.getStarSystem().getRadius();
            final int rx = (int) (radius * size.width);
            final int ry = (int) (radius * size.height);

            int x = (int) (location.getX() * size.width);
            int y = (int) (location.getY() * size.height);

            if (x + width > size.width) {
                x = (x - width) + rx;
            }

            if (y + height > size.height) {
                y = (y - height) + ry;
            }

            overlay.setBounds(x, y, width, height);
        }

        repaint();
    }
}
